package cn.tedu.d4_design;
/*
 本类测试单例模式---懒汉式！！！
 */
//总结:
//1.延迟加载的思想:是指不会在第一时间就把对象创建好来占用内存,而是什么时候需要用到,什么时候才去创建
//2.线程安全问题:是指共享资源有线程并发的数据隐患,可以通过加锁的方式[同步代码块/同步方法]
//饿汉式与懒汉式的区别:
//饿汉式是不管你用不用这个类的对象,先帮你创建一个
//懒汉式是先不给你创建这个类的对象,等你需要时再帮你创建--延迟加载的思想

public class Test2_Single2 {
    public static void main(String[] args) {

        MySingle2 m1=MySingle2.getMySingle2();
        MySingle2 m2=MySingle2.getMySingle2();

        System.out.println(m1==m2);//true
    }


}
class MySingle2{

    //1.私有化构造方法--为了防止外界调用此构造方法创建对象
    private MySingle2(){}

    //2.在类的内部创建好引用类型变量--注意私有化 -- 延迟加载
    //5.2 本处引用类型变量single也需要用static修饰,因为静态资源只能调用静态资源
    static private MySingle2 single;

    static Object obj = new Object();
    /**
     * 问题:程序中有共享资源single,并且有多条语句(3句)操作了共享资源
     * 此时single共享资源一定会存在多线程数据安全问题
     * 解决方案:加同步锁-同步代码块-同步方法[由于方法中的所有代码都被同步了,所以可以直接变成同步方法]
     * 锁的位置:操作共享资源的多条语句
     * 锁对象:static中不能使用this & 外部创建了obj,注意是static的
     * */
    //3.对外提供全局访问点
    //5.1注意要使用static来修饰本公共方法,方便后续通过类名之间调用
    synchronized static public MySingle2 getMySingle2() {

        /**同步代码块:静态区域内,不能使用this关键字,因为静态资源优先于对象this加载
         * 因为静态资源属于类资源,随着类的加载而加载,而this指的是本类对象*/

        //7.解决线程安全问题
        //synchronized (this) {//报错:Cannot use this in a static context

        synchronized (obj) {

            //4.当用户调用此方法时,才说明用到对象了,那么再将本类对象返回
            if (single == null) {//如果调用此方法时为null,说明之前没有new过,保存的是默认值null

                //没有创建对象就创建对象
                single = new MySingle2();
            }

            return single;//将本类对象返回
        }

    }




}
